﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using System.Windows.Browser;
using System.Reflection;

namespace MediaPlayerBySHF
{
    public partial class MainPage : UserControl
    {
        private IDictionary<string, object> _dicEvent = new Dictionary<string, object>();
        public MainPage()
        {
            InitializeComponent();
            HtmlPage.RegisterScriptableObject("HtmlPage", this);
        }

        #region 播放器操作
        /// <summary>
        /// 开始播放媒体
        /// </summary>
        [ScriptableMember]
        public void Play()
        {
            mediaPlayer.Play();
        }
        /// <summary>
        /// 暂停播放媒体
        /// </summary>
        [ScriptableMember]
        public void Pause()
        {
            mediaPlayer.Pause();
        }
        /// <summary>
        /// 停止播放媒体
        /// </summary>
        [ScriptableMember]
        public void Stop()
        {
            mediaPlayer.Stop();
        }
        /// <summary>
        /// 设置媒体源
        /// </summary>
        /// <param name="strMediaUrl">媒体源URL</param>
        [ScriptableMember]
        public void SetMedia(string strMediaUrl)
        {
            mediaPlayer.Source = new Uri(strMediaUrl, UriKind.RelativeOrAbsolute);
        }
        [ScriptableMember]
        public void SetVolume(double iVolume)
        {
            mediaPlayer.Volume = iVolume;
        }
        [ScriptableMember]
        public double GetCurrentPosition()
        {
            return mediaPlayer.Position.TotalSeconds;
        }
        [ScriptableMember]
        public double GetTotalDuration()
        {
            return mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds;
        }
        /// <summary>
        /// 设置是否启用自动播放
        /// </summary>
        /// <param name="isAutoPlay"></param>
        [ScriptableMember]
        public void SetAutoPlay(bool isAutoPlay)
        {
            mediaPlayer.AutoPlay = isAutoPlay;
        }
        [ScriptableMember]
        public void SetMediaPosition(double dSeconds)
        {
            if (mediaPlayer.CanSeek)
            {
                mediaPlayer.Position = TimeSpan.FromSeconds(dSeconds);
            }
        }
        #endregion 

        #region 播放器事件
        #region 公开事件
        /// <summary>
        /// 添加播放器事件
        /// </summary>
        /// <param name="strEventType">事件类型</param>
        /// <param name="strFunName">事件方法名</param>
        /// <param name="strParams">事件参数，使用JSON格式表示</param>
        /// <returns></returns>
        [ScriptableMember]
        public int AddMediaEvent(string strEventType, string strFunName, string strParams)
        {
            int strResult = 1;
            if (_dicEvent.ContainsKey(strFunName))
            {
                strResult = 0;//已包含此事件
            }
            else
            {
                try
                {
                    this.GetType().GetMethod("Add" + strEventType + "Event", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(this, new object[] { strFunName, strParams });
                }
                catch
                {
                    strResult = 2;
                }
            }
            return strResult;
        }
        /// <summary>
        /// 移除播放器事件
        /// </summary>
        /// <param name="strEventType"></param>
        /// <param name="strFunName"></param>
        [ScriptableMember]
        public void RemoveMediaEvent(string strEventType, string strFunName)
        {
            if (_dicEvent.ContainsKey(strFunName))
            {
                this.GetType().GetMethod("Remove" + strEventType + "Event", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(this, new object[] { strFunName });
                _dicEvent.Remove(strFunName);
            }
        }
        #endregion

        private void InvokeEvent(string strFunName, string strParams)
        {
            HtmlPage.Window.Invoke(strFunName, new object[] { strParams });
        }

        #region 播放器结束事件
        /// <summary>
        /// 添加播放器结束事件
        /// </summary>
        /// <param name="strMethodName">结束时要执行的JS方法名</param>
        private void AddMediaEndedEvent(string strFunName, string strParams)
        {
            RoutedEventHandler RoutedEventHandler1 = (object sender, RoutedEventArgs e) => InvokeEvent(strFunName, strParams);
            _dicEvent.Add(strFunName, RoutedEventHandler1);
            mediaPlayer.MediaEnded += (RoutedEventHandler)_dicEvent[strFunName];
        }
        /// <summary>
        /// 移除播放器结束事件
        /// </summary>
        private void RemoveMediaEndedEvent(string strFunName)
        {
            mediaPlayer.MediaEnded -= (RoutedEventHandler)_dicEvent[strFunName];
        }
        #endregion

        #region 播放器媒体加载完成时的事件
        /// <summary>
        /// 添加播放器媒体加载完成时的事件
        /// </summary>
        /// <param name="strMethodName">结束时要执行的JS方法名</param>
        private void AddMediaOpenedEvent(string strFunName, string strParams)
        {
            RoutedEventHandler RoutedEventHandler1 = (object sender, RoutedEventArgs e) => InvokeEvent(strFunName, strParams);
            _dicEvent.Add(strFunName, RoutedEventHandler1);
            mediaPlayer.MediaOpened += (RoutedEventHandler)_dicEvent[strFunName];
        }
        /// <summary>
        /// 移除播放器媒体加载完成时的事件
        /// </summary>
        private void RemoveMediaOpenedEvent(string strFunName)
        {
            mediaPlayer.MediaOpened -= (RoutedEventHandler)_dicEvent[strFunName];
        }
        #endregion

        #region 播放器状态改变事件
        /// <summary>
        /// 添加播放器状态改变事件
        /// </summary>
        /// <param name="strMethodName">结束时要执行的JS方法名</param>
        /// <param name="strParams">参数</param>
        private void AddMediaCurrentStateChangedEvent(string strFunName, string strParams)
        {
            RoutedEventHandler RoutedEventHandler1 = (object sender, RoutedEventArgs e) => InvokeEvent(strFunName, GetCurrentState());
            _dicEvent.Add(strFunName, RoutedEventHandler1);
            mediaPlayer.CurrentStateChanged += (RoutedEventHandler)_dicEvent[strFunName];
        }
        /// <summary>
        /// 移除播放器状态改变事件
        /// </summary>
        /// <param name="strMethodName">结束时要执行的JS方法名</param>
        private void RemoveMediaCurrentStateChangedEvent(string strFunName)
        {
            mediaPlayer.CurrentStateChanged -= (RoutedEventHandler)_dicEvent[strFunName];
        }
        private string GetCurrentState()
        {
            string strCurrentState;
            switch (mediaPlayer.CurrentState)
            {
                case MediaElementState.Buffering:
                    strCurrentState = "缓冲中……";
                    break;
                case MediaElementState.Opening:
                    strCurrentState = "加载中……";
                    break;
                case MediaElementState.Playing:
                    strCurrentState = "播放中……";
                    break;
                case MediaElementState.Paused:
                    strCurrentState = "已暂停";
                    break;
                case MediaElementState.Stopped:
                    strCurrentState = "已停止";
                    break;
                case MediaElementState.Closed:
                    strCurrentState = "已关闭";
                    break;
                default:
                    strCurrentState = "";
                    break;
            }
            return strCurrentState;
        }
        #endregion

        #region 播放进度改变事件
        private void AddMediaTimeUpdateEvent(string strFunName, string strParams)
        {
            EventHandler EventHandler1 = (object sender, EventArgs e) => InvokeEvent(strFunName, strParams);
            _dicEvent.Add(strFunName, EventHandler1);
            CompositionTarget.Rendering += (EventHandler)_dicEvent[strFunName];
        }
        private void RemoveMediaTimeUpdateEvent(string strFunName)
        {
            CompositionTarget.Rendering -= (EventHandler)_dicEvent[strFunName];
        }
        #endregion

        #endregion
    }
}
